package globals;

import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.FileReader;
import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

import value.*;

public class ExperimentTracker {
	
	private ArrayList<SimpleVector<?>> refSet;
	private ArrayList<SimpleVector<?>> trackSet;
	private String epsilonMeasurement;
	private ArrayList<Double> maxEpsilon;
	private ArrayList<Double> expectedEpsilon;
	private ArrayList<Long> time;
	
	private static ExperimentTracker centralTracker;
	
	public ExperimentTracker(){
		this.refSet = null;
		epsilonMeasurement = "";
		this.trackSet = new ArrayList<SimpleVector<?>>();
	}
	
	public ExperimentTracker(String refSetPath){
		this.readRefSetFromFile(refSetPath);
		epsilonMeasurement = "";
	}
	
	public void readRefSetFromFile(String refSetPath){
		ArrayList<String> sVecs = new ArrayList<String>();

	    // wrap a BufferedReader around FileReader
	    BufferedReader bufferedReader;
		try {
			bufferedReader = new BufferedReader(new FileReader(refSetPath));
			while (bufferedReader.ready())
		    {
		    	String line = bufferedReader.readLine();
		        sVecs.add(line);
		    }
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(0);
		}

		this.refSet = new ArrayList<SimpleVector<?>>(sVecs.size());
		for(int i=0; i<sVecs.size(); i++){
			SimpleVector<Integer> sv = new SimpleVector<Integer>(sVecs.get(i));
			this.refSet.add(sv);
		}
	}
	
	public <V extends SimpleVector<?>> void writeVectorSet(String prefix, ArrayList<V> vecs){
		DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
        Date date = new Date();
		String filename = "data"+prefix+dateFormat.format(date)+".txt";
		try {
			BufferedWriter bw = new BufferedWriter(new FileWriter(filename));
			for(int i=0; i<vecs.size(); i++){
				bw.write(vecs.get(i).toString()+"\n");
			}
			bw.flush();
			bw.close();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(-2);
		}
	}
	
	public void compareToRefSet(ArrayList<SimpleVector<?>> vecs){
		CPruner<SimpleVector<?>> cpr = new CPruner<SimpleVector<?>>();
		double highestLoss = Double.NEGATIVE_INFINITY;
		for(int i=0; i<this.refSet.size(); i++){
			double imp = cpr.findImprovement(this.refSet.get(i), vecs);
			if(imp>highestLoss){
				highestLoss = imp;
			}
		}
		epsilonMeasurement += StopWatch.getGlobalStopWatch().totalElapsedTime()+","+highestLoss+"\n";
	}
	
	public static ExperimentTracker getGlobalTracker(String refset){
		if(ExperimentTracker.centralTracker == null){
			if(refset!=null){
				ExperimentTracker.centralTracker = new ExperimentTracker(refset);
			} else {
				ExperimentTracker.centralTracker = new ExperimentTracker();
			}
		}
		return ExperimentTracker.centralTracker;
	}
	
	
	public void refSet2Out(){
		DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
        Date date = new Date();
		System.out.println(dateFormat.format(date));
		for(int i=0; i<this.refSet.size(); i++){
			System.out.println(this.refSet.get(i).toString());
		}
	}

	public void trackNewVec(SimpleVector<?> vec){
		SimpleVector<Boolean> nVec = new SimpleVector<Boolean>(vec.getValue());
		this.trackSet.add(nVec);
		this.compareToRefSet(this.trackSet);
		//System.out.println(this.epsilonMeasurement);
	}

}
